/**
**************************************************************************************
*Palisma - Secrets of the Illuminati is an open-source 2D RPG                        *
*Copyright (C) 2006, Tony Sparks                                                     *
*                                                                                    *
*This library is free software; you can redistribute it and/or                       *
*modify it under the terms of the GNU Lesser General Public                          *
*License as published by the Free Software Foundation; either                        *
*version 2.1 of the License, or (at your option) any later version.                  *
*                                                                                    *
*This library is distributed in the hope that it will be useful,                     *
*but WITHOUT ANY WARRANTY; without even the implied warranty of                      *
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                   *
*Lesser General Public License for more details.                                     *
*                                                                                    *
*You should have received a copy of the GNU Lesser General Public                    *
*License along with this library; if not, write to the Free Software                 *
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA      *
**************************************************************************************
*/
#pragma once
#include "Myriad.h"
#include "Timer.h"

/**
 * Buffer ids
 */
enum {
    BUFFER_CONSOLE
};


/**
==========================
The Heart of the MyriadEngine
The kernel decides which process runs, and
holds all subsystems
==========================
*/
class Kernel
{
public:
    Kernel(void);

    /** Init the kernel */
    int Init();
    /** Shutdown all Processes */
    void Shutdown();
    /** Run the kernel */
    void Execute();

    /** Add a process */
	void AddProcess(CMMPointer<IProcess> &p);
    /** Suspend a process */
	void SuspendProcess(CMMPointer<IProcess> &p);
    /** Resume a process */
	void ResumeProcess(CMMPointer<IProcess> &p);
    /** Remove a process */
	void RemoveProcess(CMMPointer<IProcess> &p);
    /** Kill all the processes */
	void KillAll();

    /** Get the current time */
    float GetTime();
    /** Get the time between last frame and the current one */
    float GetFrameTime();
    /** Timer object */
    Timer& GetTimer() { return timer; };

    /**
     *   Retrieve a subsystem
     */

    /** The Input System */
    CMMPointer<IInput>& GetInput() { return m_input; };
    /** Sound System */
    CMMPointer<ISound>& GetSound() { return m_sound; };
    /** The Renderer System */
    CMMPointer<IRenderManager>& GetRenderer() { return m_renderer; };
    /** Resource Manager System */
    CMMPointer<Resource>& GetResource() { return m_resource; };
    /** Scripting Engine System */
    CMMPointer<ScriptEngine>& GetScriptEngine() { return m_scripter; };
    /** The game System */
    CMMPointer<GameManager>& GetGame() { return m_game; };
    
    /** Console subsystem */
    Console* GetConsole() { return m_console; };
    /** Cvar System */
    CMMPointer<Cvars>& GetCvars() { return m_cvars; };

    /** Useful functions */

    /** Print to console */
    void Printf( const char *s, ... );
    /** Log */
    void LPrintf( const char *s, ... );

    /**
    =========================
    Add the subsystems
    =========================
    */
    void SetScriptEngine(CMMPointer<ScriptEngine> &s) {
        m_scripter = s;
    };

    void SetResource(CMMPointer<Resource> &r) {
        m_resource = r;
    };
    void SetInput(CMMPointer<IInput> &in) {
        m_input = in;
    };

    void SetGame(CMMPointer<GameManager> &g) {
        m_game = g;
    };
    void SetRenderer( CMMPointer<IRenderManager> &r) {
        m_renderer = r;
    };
    void SetSound( CMMPointer<ISound> &s) {
        m_sound = s;
    };
    void SetConsole( Console* c ) {
        m_console = c;
    };
    void SetCvars( CMMPointer<Cvars> &c ) {
        m_cvars = c;
    };
public:
    virtual ~Kernel(void);

private:
    std::list< CMMPointer<IProcess> > proList;
    std::list< CMMPointer<IProcess> > pausedList;

    CMMPointer<IInput>          m_input;
    CMMPointer<GameManager>     m_game;
    CMMPointer<IRenderManager>  m_renderer;
    CMMPointer<ISound>          m_sound;

    CMMPointer<Resource>        m_resource;

    CMMPointer<ScriptEngine>    m_scripter;
    
    // Debugging
    Console*                    m_console;
    CMMPointer<Cvars>           m_cvars;
    

    long                        m_lastFrame;
    long                        m_delta;
    Timer                       timer;
};

